﻿// See https://aka.ms/new-console-template for more information
//访问者模式
//访问者模式是一种行为型设计模式，他允许你在不改变对象结构的情况下，定义对其元素的新操作。

//在软件开发中，有时也需要处理像是处方单这样的集合对象结构，在该对象中存储了多种不同类型的对象信息，而且对于同一个对象的操作可能会不一样。可能需要提供多种数据处理方法，还可能会增加新的数据处理方法，为了解决这种问题，访问者模式诞生了，他可以以不同的方式操作复杂对象结构。

//访问者模式包含五个对象
//·Visitor（抽象访问者）：抽象访问者为每一个具体的元素类声明了一个访问操作，具体的操作将由其子类实现。
//·ConcreteVisitor（具体访问者）：具体访问者实现了抽象访问者为每个具体元素类声明的抽象操作。
//·Element（抽象元素）：抽象元素声明了一个Accept方法，用于接受访问者的访问，参数列表中需要传入一个访问者。
//·ConcreteElement（具体元素）：具体元素实现抽象元素中的Accept方法
//·ObjectStructure（对象结构）：对象结构是一个元素集合用于存放元素对象，此项并不是必须要有的一个对象。
var shapes = new List<Shape>
{
    new Cirle{Radius=10.0},
    new Rectangle{Height=10.0,Width=10.0},
    new Triangle{Base=5.0,Height= 10.0}
};

var areVisitor = new AreaVisitor();//面积访问者

foreach (var item in shapes)
{
    item.Accept(areVisitor);
}
Console.WriteLine("圆形面积为:"+ areVisitor.CirecleArea);
Console.WriteLine("矩形面积为:"+ areVisitor.RectangleArea);
Console.WriteLine("三角形面积为:"+ areVisitor.TriangleArea);

Console.WriteLine("Hello, World!");

//访问者模式是一种行为型设计模式，它允许你将算法与对象结构分离开来，使得算法可以独立于对象结构而变化。该模式的核心思想是，定义一个访问者类，该类可以访问不同类型的对象，并对这些对象执行不同的操作。

//假设我们有一个图形类，它有三个子类：圆形、矩形和三角形。我们想要实现一个计算图形面积的功能，但是我们不想在每个子类中都实现这个功能，因为这样会导致代码重复。我们可以使用访问者模式来解决这个问题。

//首先，我们定义一个访问者接口，该接口包含三个方法，分别用于访问圆形、矩形和三角形：
internal interface IShapeVisitor
{
    void VisitCircle(Cirle cirle);

    void VisitRectangle(Rectangle rectangle);

    void VisitTriangle(Triangle triangle);
}

//然后我们定义一个图形类，该类包含一个Accept方法，该方法接受一个访问者对象，并调用访问者对象中相应的方法
internal abstract class Shape
{
    public abstract void Accept(IShapeVisitor visitor);
}

//接下来，我们定义三个图形子类，分别实现Accept方法
internal class Cirle : Shape
{
    //圆形半径
    public double Radius { get; set; }

    public override void Accept(IShapeVisitor visitor)
    {
        visitor.VisitCircle(this);
    }
}

internal class Rectangle : Shape
{
    //矩形宽
    public double Width { get; set; }

    //矩形高
    public double Height { get; set; }

    public override void Accept(IShapeVisitor visitor)
    {
        visitor.VisitRectangle(this);
    }
}

internal class Triangle : Shape
{
    //三角形低
    public double Base { get; set; }

    //三角形高
    public double Height { get; set; }

    public override void Accept(IShapeVisitor visitor)
    {
        visitor.VisitTriangle(this);
    }
}

//最哦，我们定义一个计算面积的访问者类，该类实现了IShapeVisitor接口，并且实现了VisitCircle，VisitRectangle，VisitTriangle方法
internal class AreaVisitor : IShapeVisitor
{
    public double CirecleArea { get; private set; }
    public double RectangleArea { get; private set; }
    public double TriangleArea { get; private set; }

    public void VisitCircle(Cirle cirle)
    {
        CirecleArea = Math.PI * cirle.Radius * cirle.Radius;
    }

    public void VisitRectangle(Rectangle rectangle)
    {
        RectangleArea = rectangle.Width * rectangle.Height;
    }

    public void VisitTriangle(Triangle triangle)
    {
        TriangleArea = 0.5 * triangle.Base * triangle.Height;
    }
}